<?php

class base_session
{
    // session id
    private $_sess_id;

    // session key
    private $_sess_key = 's';

    // session 是否已经启动
    private $_session_started = false;

    // session 有效期 单位 分钟
    private $_sess_expires = 60;

    // cookie 有效期 单位 分钟
    private $_cookie_expires = 0;

    // session 是否被销毁
    private $_session_destoryed = false;

    public function __construct()
    {
        $config = config::get('session');
        $this->_sess_key = $config['cookie'] ? : 's';
        $this->_sess_expires = $config['lifetime'] ? : 60;
    }

    public function start()
    {
        if ($this->_session_started !== true) {

            if (strlen($_COOKIE[$this->_sess_key]) == 40) {
                $this->_sess_id = $_COOKIE[$this->_sess_key];
                $_SESSION = $this->_get_session();

            } elseif (!$this->_sess_id) {
                $this->_sess_id = $this->gen_session_id();
                $_SESSION = [];
                $this->set_cookie_expires($this->_cookie_expires);
            }

            $this->_session_started = true;
            register_shutdown_function(array(&$this, 'close'));
        }

        return true;
    }

    public function close($writeBack = true)
    {
        if (!$this->_session_started || $this->_session_started !== true) {
            return false;
        }

        if (strlen($this->_sess_id) != 40) {
            return false;
        }

        $this->_session_started = false;

        if (!$writeBack) {
            return false;
        }

        if ($this->_session_destoryed) {
            return true;
        } else {
            return $this->_set_session($_SESSION, $this->_sess_expires);
        }
    }

    public function set_cookie_expires($minute = 0)
    {
        $this->_cookie_expires = ($minute > 0) ? $minute : 0;
        if ($this->_sess_id) {
            $cookie_path = kernel::base_url() ? : '/';
            // header(sprintf('Set-Cookie: %s=%s; path=%s; expires=%s; httpOnly;', $this->_sess_key, $this->_sess_id, $cookie_path, gmdate('D, d M Y H:i:s T', time() + $minute * 60)), true);
            $expires = empty($this->_cookie_expires) ? $this->_cookie_expires : (time() + $this->_cookie_expires * 60);
            setcookie($this->_sess_key, $this->_sess_id, $expires, $cookie_path);
        }
    }

    public function set_sess_expires($minute)
    {
        $this->_sess_expires = $minute;
    }

    public function sess_id()
    {
        return $this->_sess_id;
    }

    private function _get_cache_key()
    {
        return 'USER_SESSION:' . $this->sess_id();
    }

    private function _set_session($value, $minutes)
    {
        return cache::store('session')->put($this->_get_cache_key(), $value, $minutes);
    }

    private function _get_session()
    {
        if ($return = cache::store('session')->get($this->_get_cache_key())) {
            return $return;
        } else {
            return array();
        }
    }

    protected function gen_session_id()
    {
        return sha1(uniqid('', true) . request::getClientIp() . str_random(25) . microtime(true));
    }

    public function destory()
    {
        if (!$this->_session_started) {
            return false;
        }
        $this->_session_started = false;
        $res = $this->_set_session([], 1);
        if ($res) {
            $_SESSION = [];
            $this->_session_destoryed = true;
            $this->set_cookie_expires(0);
            unset($this->_sess_id);
            return true;
        } else {
            return false;
        }
    }
}